package com.diuse.outer.util.helper;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.log4j.Logger;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Utility class for java bean.
 * @author fumingjie
 */
public final class BeanHelper {
	static Logger log = Logger.getLogger(BeanHelper.class);
    /**
     * Invoke get mathod to fetch named value from target bean.
     * @param object An object
     * @param name field name
     * @return named value
     */
    public static Object getValue(final Object object, final String name) {
        if (name == null || "".equals(name.trim())) {
            throw new IllegalArgumentException("Argument 'name' must not be null!");
        }
        String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
        Method m = ClazzHelper.getMethod(object.getClass(), getter);
        return m == null ? null : invoke(object, m, new Object[]{});
    }

    /**
     * Invoke set mathod to set value for target bean.
     * @param object An object
     * @param name Field name
     * @param value Value to set
     */
    public static void setValue(final Object object, final String name, final Object value) {
        if (name == null || "".equals(name.trim())) {
            throw new IllegalArgumentException("Argument 'name' must not be null!");
        }

        String setter = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
        Field field = ClazzHelper.getDeclaredField(object.getClass(), name);
        Method m = ClazzHelper.getMethod(object.getClass(), setter);

        if (m != null) {
        	invoke(object, m, new Object[]{convert(field.getType(), value)});
        }
    }

    /**
     * Invoke a method from EISTo.
     * @param object An object
     * @param m Method
     * @param args mehtod arguments
     * @return Object value if has
     */
    public static Object invoke(final Object object, final Method m, final Object[] args) {
        if (object == null) {
            throw new NullPointerException("Argument domain(Domain) must not be null!");
        }

        try {
            return m.invoke(object, args);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Convert object value to certain class type.
     * @param type Class type for converting
     * @param value value to convert
     * @return value after converted.
     */
    public static Object convert(final Class<? extends Object> type, final Object value) {
        if (type.getName().equals("java.util.Date")) {
            if (value != null && value instanceof String) {
                return DateHelper.date(value.toString());
            }

            return value;
        }

        Converter converter = ConvertUtils.lookup(type);
        if (converter == null) {
            return value;
        }

        return converter.convert(type, value);
    }

    /**
     * Copy properties from srcDomain to targetDomain.
     * @param srcDomain Source domain
     * @param targetDomain Target domain
     */
    public static void copy(final Object srcDomain, final Object targetDomain) {
        if (srcDomain == null || targetDomain == null) {
            log.warn("Source or target domain, nothing copied");
            return;
        }
        if (!srcDomain.getClass().getName().equals(targetDomain.getClass().getName())) {
            throw new RuntimeException("Source or target domain must construct from the same class");
        }
        
        List<Field> targeFields = ClazzHelper.getDeclaredFields(targetDomain.getClass());
        for (Field field : targeFields) {
            setValue(targetDomain, field.getName(), getValue(srcDomain, field.getName()));
        }
    }

    
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, ReflectiveOperationException {
		Class clazz = Class.forName("java.lang.Class");
		System.out.println(clazz.getName());
//		Method m = clazz.getDeclaredMethod("isAnnotation", null);
//		System.out.println("modify is: " + m.getModifiers());
//		System.out.println(m.getName());
//		m.setAccessible(false);
//		System.out.println("modify is: " + m.getModifiers());
//		m.invoke(obj, args)
//		System.out.println("modify is: " + m.getModifiers());
		Constructor constructor = clazz.getDeclaredConstructor();
		System.out.println("111");
		constructor.getModifiers();
		constructor.setAccessible(true);
		Object object = constructor.newInstance();
		System.out.println("2222");
//		System.out.println(object.getClass().getName());
	
	}
    
    /**
    * Constructor.
    */
    private BeanHelper() { }
}
